﻿using FinanceAPI.Common;
using FinanceAPI.Core;
using FinanceAPI.Model;
using FinanceAPI.Model.Dappers;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;

namespace FinanceAPI.Services
{
    public class VourcherService
    {
        private readonly FinanceDbContext _context;
        private readonly IConfiguration _configuration;
        private readonly IOptions<MonthlyCalcDay> _settings;
        private readonly ILogger _logger;
        private readonly string _dbConn;
        /// <summary>
        /// FinanceService
        /// </summary>
        /// <param name="context"></param>
        /// <param name="configuration"></param>
        /// <param name="loggerFactory"></param>
        /// <param name="settings"></param>
        public VourcherService(FinanceDbContext context, IConfiguration configuration, ILoggerFactory loggerFactory, IOptions<MonthlyCalcDay> settings)
        {
            _context = context;
            _configuration = configuration;
            _logger = loggerFactory.CreateLogger<VourcherService>();
            _settings = settings;
            _dbConn = _configuration.GetConnectionString("dbconn");
        }
        Tools tl = new Tools();
        ZipTools zt = new ZipTools();
        DapperHelper dh = new DapperHelper();
        public async Task<string> Vourcher(JsonData value)
        {

            if (!string.IsNullOrEmpty(value.Remark))
            {
                await AddLog(string.Empty, string.Empty, $"{value.GroupName}--前置机接口异常:{value.Remark}");
                return $"{value.GroupName}--前置机接口异常:{value.Remark}";
            }

            //科目余额同步(开启线程优先单独去同步)
            var vourcherInfo = string.Empty;
            try
            {
                var balanceInfo = string.Empty;
                if (_settings.Value.IsOpenBalanceSync)
                {
                    balanceInfo = await Task.Run(() => AddBalances(value.GroupCode, value.GroupName, value.Balances));
                   // _logger.LogInformation("余额:  "+value.Balances);
                   // balanceInfo = AddBalances(value.GroupCode, value.GroupName, value.Balances);
                }

                if (!_settings.Value.IsVourcherSync)
                {
                    await AddLog(value.GroupCode, balanceInfo, "凭证同步没有开启!");
                    return $"凭证同步没有开启,{balanceInfo}";
                }

                // var vourcher = tl.Decrypt(value.Vourchers);//解密 4.6写法
                // vourcher = zt.GZipDecompressString(Encoding.GetEncoding("utf-8"), vourcher);//先base64还原、再来解压

                // _logger.LogInformation("解压前 :" + value.Vourchers);
                //    _logger.LogInformation("\r\n解压后:" + zt.GZipDecompressString(Encoding.GetEncoding("utf-8"), tl.Decrypt(value.Vourchers)));
                var vourchers = zt.GZipDecompressString(Encoding.GetEncoding("utf-8"), tl.Decrypt(value.Vourchers)).ToObject<List<PdEntityVourcher>>().OrderBy(t => t.记账日期).ToList();//序列化为凭证对象 
                  // _logger.LogInformation("\r\n解压后:" + vourchers.ToJson());


                var isMonthlyCalc = false;
                //判断是否月计算
                if (_settings.Value.IsMonthlyCalc && DateTime.Now.Day == _settings.Value.CalcDay)
                {
                    vourcherInfo += _settings.Value.IsMonthlyCalc.ToString() + _settings.Value.CalcDay;
                    isMonthlyCalc = true;
                    //获取上个月第一天
                    var startDay = GetFirstDayOfLastMonth();
                    //上一月最后一天
                    var monthLastDay = GetLastDayOfLastMonth();

                    vourcherInfo += $"月度同步时间{startDay}--{monthLastDay},一共{vourchers.Count}条";

                    vourchers = vourchers.Where(t => t.记账日期 <= monthLastDay && t.记账日期 >= startDay).OrderBy(t => t.记账日期).ToList();
                    vourcherInfo += $"过滤后条数:{vourchers.Count}条";

                    //删除当前库中上月凭证(包括辅助账，核算项)、中间表、预警表数据
                    ResetDate(startDay.ToString("yyyy-MM-dd"), monthLastDay.ToString("yyyy-MM-dd"), value.GroupCode, false);
                }

                vourcherInfo += await WarninCalculation(vourchers, value.GroupCode, value.GroupName, isMonthlyCalc);

                await AddLog(value.GroupCode, balanceInfo, vourcherInfo);
            }
            catch (Exception ex)
            {
                await AddLog(value.GroupCode, "", $"预警计算异常:{ex.Message}");
                return $"预警计算异常:{ex.Message}";
            }
            _logger.LogInformation(vourcherInfo);
            return vourcherInfo;
        }

        /// <summary>
        /// 重新计算
        /// </summary>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="groupCode"></param>
        /// <param name="groupName"></param>
        /// <returns></returns>
        public async Task<string> NewVourcherCalc(string startDate, string endDate, string groupCode, string groupName)
        {
            //删除中间表记账日期，预警表记账日期
            ResetDate(startDate, endDate, groupCode, true);

            var vourchers = _context.PdVourchers.Include(u => u.凭证辅助账).ThenInclude(u => u.核算项).Where(t => t.集团代码 == groupCode && t.记账日期 >= Convert.ToDateTime(startDate) && t.记账日期 <= Convert.ToDateTime(endDate)).OrderBy(t => t.记账日期).ToList();

            return await NewVourcherCalculation(vourchers, groupCode, groupName);//凭证数据不入库
        }

        /// <summary>
        /// 重新预警计算
        /// </summary>
        /// <param name="vourchers"></param>
        /// <param name="groupCode"></param>
        /// <param name="groupName"></param>
        /// <returns></returns>
        public async Task<string> NewVourcherCalculation(List<PdEntityVourcher> vourchers, string groupCode, string groupName)
        {
            if (vourchers.Count == 0) return string.Empty;
            var sb = new StringBuilder();
            var startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            var listGroup = new List<List<PdEntityVourcher>>();
            var j = 2000;
            for (var i = 0; i < vourchers.Count; i += 2000)
            {
                var cList = vourchers.Take(j).Skip(i).ToList();
                j += 2000;
                listGroup.Add(cList);
            }
            try
            {
                var subjects = GetEntitys<PdEntitySubject>($"select GroupID,SubjectCode,SubjectSign,IsWarning from Pd_SubjectCode where GroupId = '{groupCode}'");

                var projects = GetEntitys<PdEntityVourcherProject>($"select GroupId,CompanyCode,CompanyName,CompanyUniqueId,ProjectCode,ProjectName,Threshold ,CountFlag,BigProjectCode,BigProjectName from Pd_Vourcher_Project where GroupId = '{groupCode}'");

                var debits = GetEntitys<PdEntityDebit>($"select * from Pd_Debit where GroupId = '{groupCode}' ");

                var customers = GetEntitys<PdEntityVourcherCustomer>($"select GroupId, CompanyCode ,CompanyName,CompanyUniqueId,CustomerName,CustomerCode,Threshold ,InternalCustomer from Pd_Vourcher_Customer where GroupId = '{groupCode}'");

                var organizations = GetEntitys<PdEntityOrganization>($"select GroupId,CompanyCode,CompanyName ,Threshold,InflowThreshold,IsProjectCompany,IsInflowWarning from Pd_Organization where GroupId = '{groupCode}'");

                var varcherWarnings = new List<PdEntityVourcherWarning>();
                var vourcherDebits = new List<PdEntityDebit>();
                foreach (var group in listGroup)
                {
                    foreach (var v in group.ToArray())
                    {
                        v.ID = Guid.NewGuid();
                        v.集团代码 = groupCode;
                        v.集团名称 = groupName;
                        v.公司唯一代码 = $"{groupCode}-{v.公司编码}";
                        var code = GetSubjectTag(v, subjects, customers);
                        if (!string.IsNullOrEmpty(code))
                            v.科目分类 = code;

                        if (subjects.Any(t => t.SubjectSign == v.科目分类 && t.IsWarning))
                        {
                            v.流入资金 = !v.借贷方向;

                            if (v.公司编码 == "630883397" && v.集团代码 == "0004")
                                continue;

                            if (!v.借贷方向) //流入资金直接判断凭证
                            {
                                var isInflowWarning = false;
                                //流入资金不预警判断--isInflowWarning
                                var organization = organizations.FirstOrDefault(t =>
                                    t.GroupId == v.集团代码 && t.CompanyCode == v.公司编码);

                                if (organization != null)
                                {
                                    if (organization.IsInflowWarning)
                                    {
                                        isInflowWarning = true;
                                    }
                                }
                                if (isInflowWarning)
                                {
                                    var result = VourcherProcessing(organizations, v);
                                    if (result != null)
                                        varcherWarnings.Add(result);
                                }
                            }
                            else//流出预警
                            {
                                if (!v.凭证类型.Contains("收"))//流出资金凭证类型含有收的不计算
                                {
                                    //增加是否是项目公司逻辑，
                                    var isProjectCompany = false;
                                    var organization = organizations.FirstOrDefault(t =>
                                        t.GroupId == v.集团代码 && t.CompanyCode == v.公司编码);
                                    if (organization != null)
                                    {
                                        if (organization.IsProjectCompany)//如果是项目公司 进行项目公司逻辑计算
                                        {
                                            isProjectCompany = true;
                                            //项目公司预警计算
                                            var result = ProjectCompanyProcessing(v, organization, ref debits, ref vourcherDebits);
                                            if (result != null && result.Count > 0)
                                                varcherWarnings.AddRange(result);
                                        }
                                    }

                                    if (!isProjectCompany)
                                    {
                                        var dicc = GetSubsidiary(v); //获取当前凭证的 辅助账明细 存于字典中  项目/客商

                                        if (dicc.Item1.Count > 0 || dicc.Item2.Count > 0)
                                        {
                                            //3逻辑计算
                                            if (dicc.Item1.Count > 0)//项目匹配到了
                                            {
                                                //项目预警计算
                                                var result = ProjectProcessing(dicc.Item1, projects, v, ref debits, ref vourcherDebits, customers);
                                                if (result != null && result.Count > 0)
                                                    varcherWarnings.AddRange(result);
                                            }
                                            else
                                            {
                                                if (dicc.Item2.Count > 0)//客商匹配到了
                                                {
                                                    var result = CustomerProcessing(dicc.Item2, customers, v, ref debits, ref vourcherDebits);
                                                    if (result != null && result.Count > 0)
                                                        varcherWarnings.AddRange(result);
                                                }
                                                else//凭证预警
                                                {
                                                    var result = VourcherProcessing(organizations, v);
                                                    if (result != null)
                                                        varcherWarnings.Add(result);
                                                }
                                            }

                                        }
                                        else//凭证计算
                                        {
                                            var result = VourcherProcessing(organizations, v);
                                            if (result != null)
                                                varcherWarnings.Add(result);
                                        }
                                        dicc.Item1.Clear();
                                        dicc.Item2.Clear();
                                    }
                                }
                            }
                        }
                        else
                        {//在四大科目内的流入资金方向判断
                            v.流入资金 = v.科目分类 == "0" ? v.借贷方向 : !v.借贷方向;
                        }
                    }
                }
                BulkInsertObject.BulkInsert(_dbConn, "Pd_Debit", vourcherDebits);//插入中间表
                BulkInsertObject.BulkInsert(_dbConn, "Pd_Vourcher_Warning", varcherWarnings);//插入预警表

                var endTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                sb.Append($"全部处理完成!一共凭证{vourchers.Count}条\r\n" +
                         $"开始解析时间:{startTime}\r\n"
                         + $"处理完成时间:{endTime}\r\n");

                //重新计算完毕之后需要验证数据准确性，
                // sb.Append(CheckData());

            }
            catch (Exception ex)
            {
                return $"凭证重新计算异常:{ex.Message}";
            }
            return sb.ToString();

        }


        /// <summary>
        /// 预警计算
        /// </summary>
        /// <param name="vourchers"></param>
        /// <param name="groupCode"></param>
        /// <param name="groupName"></param>
        /// <param name="isMonthlyCalc"></param>
        /// <returns></returns>
        public async Task<string> WarninCalculation(List<PdEntityVourcher> vourchers, string groupCode, string groupName, bool isMonthlyCalc)
        {
            var sb = new StringBuilder();
            var startTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            var listGroup = new List<List<PdEntityVourcher>>();
            var j = 2000;
            var vourcherCount = vourchers.Count;
            _logger.LogInformation($"{groupName}--凭证解密后数据条目:{vourcherCount}");
            for (var i = 0; i < vourcherCount; i += 2000)
            {
                var cList = vourchers.Take(j).Skip(i).ToList();
                j += 2000;
                listGroup.Add(cList);
            }
            try
            {
                var subjects = GetEntitys<PdEntitySubject>($"select GroupID,SubjectCode,SubjectSign,IsWarning from Pd_SubjectCode where GroupId = '{groupCode}'");

                var debits = new List<PdEntityDebit>();
                var vourcherDebits = new List<PdEntityDebit>();
                if (isMonthlyCalc)
                {
                    debits = GetEntitys<PdEntityDebit>($"select * from Pd_Debit where GroupId = '{groupCode}' and PostingDate<='{GetLastDayOfLastMonth().ToString("yyyy-MM-dd")}' ");
                }
                else
                {
                    debits = GetEntitys<PdEntityDebit>($"select * from Pd_Debit where GroupId = '{groupCode}' ");
                }

                var projects = GetEntitys<PdEntityVourcherProject>($"select GroupId,CompanyCode,CompanyName,CompanyUniqueId,ProjectCode,ProjectName,Threshold ,CountFlag ,BigProjectCode,BigProjectName from Pd_Vourcher_Project where GroupId = '{groupCode}'");

                var customers = GetEntitys<PdEntityVourcherCustomer>($"select GroupId,   CompanyCode  ,CompanyName,CompanyUniqueId,CustomerName,CustomerCode,Threshold ,InternalCustomer from Pd_Vourcher_Customer where GroupId = '{groupCode}'");


                var organizations = GetEntitys<PdEntityOrganization>($"select GroupId,CompanyCode ,Threshold,InflowThreshold, IsProjectCompany,CompanyName,IsInflowWarning from Pd_Organization where GroupId = '{groupCode}'");

                var varcherWarnings = new List<PdEntityVourcherWarning>();
                foreach (var group in listGroup)
                {
                    foreach (var v in group.ToArray())
                    {
                        v.ID = Guid.NewGuid();
                        v.集团代码 = groupCode;
                        v.集团名称 = groupName;
                        v.公司唯一代码 = $"{groupCode}-{v.公司编码}";
                        var code = GetSubjectTag(v, subjects, customers);
                        if (!string.IsNullOrEmpty(code))
                            v.科目分类 = code;

                        if (subjects.Any(t => t.SubjectSign == v.科目分类 && t.IsWarning))
                        {
                            v.流入资金 = !v.借贷方向;

                            if(v.公司编码== "630883397"&&v.集团代码=="0004")
                                continue;

                            if (!v.借贷方向)//借贷方向为0  ----流入资金直接判断凭证
                            {
                                var isInflowWarning = false;
                                //流入资金不预警判断--isInflowWarning
                                var organization = organizations.FirstOrDefault(t =>
                                    t.GroupId == v.集团代码 && t.CompanyCode == v.公司编码);

                                if (organization != null)
                                {
                                    if (organization.IsInflowWarning)
                                    {
                                        isInflowWarning = true;
                                    }
                                }
                                //判断 是否参与流入预警  不参与直接跳过
                                if (isInflowWarning)
                                {
                                    var warning = VourcherProcessing(organizations, v);
                                    if (warning != null)
                                        varcherWarnings.Add(warning);
                                }
                            }
                            else
                            {
                                //流出资金
                                if (!v.凭证类型.Contains("收"))
                                {
                                    //获取当前凭证的 辅助账明细 存于字典中  项目/客商
                                    var dicc = GetSubsidiary(v);
                                    //增加是否是项目公司逻辑，
                                    var isProjectCompany = false;
                                    var organization = organizations.FirstOrDefault(t =>
                                        t.GroupId == v.集团代码 && t.CompanyCode == v.公司编码);
                                    if (organization != null)
                                    {
                                        if (organization.IsProjectCompany)//如果是项目公司 进行项目公司逻辑计算
                                        {
                                            isProjectCompany = true;
                                            //项目公司预警计算
                                            var result = ProjectCompanyProcessing(v, organization, ref debits, ref vourcherDebits);
                                            if (result != null && result.Count > 0)
                                                varcherWarnings.AddRange(result);
                                        }
                                    }
                                    if (!isProjectCompany)
                                    {
                                        if (dicc.Item1.Count > 0 || dicc.Item2.Count > 0)
                                        {
                                            //3逻辑计算
                                            if (dicc.Item1.Count > 0) //项目匹配到了
                                            {
                                                //项目预警计算
                                                var result = ProjectProcessing(dicc.Item1, projects, v, ref debits, ref vourcherDebits, customers, isMonthlyCalc);
                                                if (result != null && result.Count > 0)
                                                    varcherWarnings.AddRange(result);
                                            }
                                            else
                                            {
                                                if (dicc.Item2.Count > 0) //客商匹配到了
                                                {
                                                    var result = CustomerProcessing(dicc.Item2, customers, v, ref debits, ref vourcherDebits, isMonthlyCalc);
                                                    if (result != null && result.Count > 0)
                                                        varcherWarnings.AddRange(result);
                                                }
                                                else //凭证预警
                                                {
                                                    var result = VourcherProcessing(organizations, v);
                                                    if (result != null)
                                                        varcherWarnings.Add(result);
                                                }
                                            }
                                            dicc.Item1.Clear();
                                            dicc.Item2.Clear();
                                        }
                                        else
                                        {
                                            var result = VourcherProcessing(organizations, v);
                                            if (result != null)
                                                varcherWarnings.Add(result);
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {//在四大科目内的流入资金方向判断
                            v.流入资金 = v.科目分类 == "0" ? v.借贷方向 : !v.借贷方向;
                        }
                    }
                    debits = AddVourcher(groupCode, group, vourcherDebits, varcherWarnings);//数据入库（凭证、中间表、预警数据）
                    vourcherDebits.Clear();
                    varcherWarnings.Clear();
                }

                var endTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                sb.Append($"全部处理完成!一共凭证{vourchers.Count}条\r\n" +
                         $"开始解析时间:{startTime}\r\n"
                         + $"处理完成时间:{endTime}");
            }
            catch (Exception ex)
            {
                return $"凭证数据插入异常:{ex.Message}";
            }
            return sb.ToString();
        }

        private async Task AddLog(string groupCode, string balanceLog, string vourcherLog)
        {
            _context.PdVourcherLogs.Add(new PdEntityVourcherLog
            {
                GroupCode = groupCode,
                BalancesInfo = balanceLog,
                VourchersInfo = vourcherLog,
                LogLevel = balanceLog.Contains("异常") || vourcherLog.Contains("异常") ? 2 : 1
            });
            await _context.SaveChangesAsync();
        }


        private void ResetDate(string startDate, string endDate, string groupCode, bool isNewCount)
        {
            //1.删除 预警表和中间表
            var delSql = "delete from[dbo].[Pd_Vourcher_Warning] where PostingDate " +
                         $"BETWEEN '{startDate}' AND '{endDate}' and groupId='{groupCode}';" +
                         $"delete from[dbo].[Pd_Debit] where PostingDate BETWEEN  '{startDate}' AND '{endDate}' and groupId='{groupCode}';";

            if (!isNewCount)//如果是系统手动重新计算则不需要删除凭证及凭证辅助账
            {
                //删除辅助账
                delSql += "delete Pd_Vourcher_Check_Account where id in(" +
                           "select id from Pd_Vourcher_Check_Account a where a.凭证辅助账ID in(" +
                           " select id from Pd_Vourcher_Subsidiary s where s.PdEntityVourcherId in(" +
                           $" select id from Pd_Vourcher where 记账日期 >= '{startDate}'and 记账日期 <= '{endDate}' and 集团代码='{groupCode}')));" +
                           "delete Pd_Vourcher_Subsidiary where id in(" +
                           "select id from Pd_Vourcher_Subsidiary s where s.PdEntityVourcherId in(" +
                           $"select id from Pd_Vourcher where 记账日期 >= '{startDate}'and 记账日期 <= '{endDate}' and 集团代码='{groupCode}'));" +
                           $"delete  from Pd_Vourcher where 记账日期 >= '{startDate}'and 记账日期 <= '{endDate}' and 集团代码='{groupCode}';";
            }
            dh.Execute(delSql, _dbConn);
        }

        private List<T> GetEntitys<T>(string sql)
        {
            return dh.GetEntitys<T>(sql, _dbConn);
        }

        private List<PdEntityVourcherWarning> CustomerProcessing(Dictionary<string, string> dicc, List<PdEntityVourcherCustomer> customers, PdEntityVourcher v, ref List<PdEntityDebit> debits, ref List<PdEntityDebit> voucherDebits, bool isMonthlyCalc = false)
        {
            var warnings = new List<PdEntityVourcherWarning>();
            foreach (var item in dicc)//客商匹配加上companycode 
            {
                var code = customers.FirstOrDefault(t =>
                    t.CustomerCode == item.Key && t.CustomerName == item.Value);
                debits.Add(NewDebit(v, 2, item.Key, item.Value, string.Empty)); //累计前先插入此次记录在进行累计
                voucherDebits.Add(NewDebit(v, 2, item.Key, item.Value, string.Empty));
                var fzz = v.凭证辅助账.FirstOrDefault(t => t.核算项.FirstOrDefault(r => r.编码 == item.Key) != null);

                if (code != null)
                {
                    //外部客商预警
                    var warning = ExternalCustomerWarning(code, fzz.原币金额, v, item, debits, isMonthlyCalc);
                    if (warning != null)
                        warnings.Add(warning);
                }
                else
                {
                    warnings.Add(NewVourcherWarning(v, WarningType.Customer, item.Key, item.Value, fzz.原币金额,
                        $"新客商[{item.Value}]")); //插入预警表 新客商预警
                }
            }
            return warnings;
        }

        private List<PdEntityDebit> AddVourcher(string groupCode, List<PdEntityVourcher> group, List<PdEntityDebit> vourcherDebits, List<PdEntityVourcherWarning> varcherWarnings, bool isAddVourcher = true)
        {
            if (isAddVourcher)
            {
                var fzzList = new List<凭证辅助账>();
                foreach (var item in group)
                {
                    if (item.凭证辅助账 != null)
                    {
                        foreach (var r in item.凭证辅助账)
                        {
                            r.PdEntityVourcherId = item.ID;
                        }
                        fzzList.AddRange(item.凭证辅助账);
                    }
                }

                var hsxList = new List<核算项>();

                foreach (var item in fzzList)
                {
                    foreach (var r in item.核算项)
                    {
                        r.凭证辅助账ID = item.ID;
                    }
                    hsxList.AddRange(item.核算项);
                }
                BulkInsertObject.BulkInsert(_dbConn, "Pd_Vourcher_Check_Account", hsxList);//插入核算项

                BulkInsertObject.BulkInsert(_dbConn, "Pd_Vourcher_Subsidiary", fzzList);//插入辅助账

                BulkInsertObject.BulkInsert(_dbConn, "Pd_Vourcher", group.OrderBy(t => t.记账日期).ToList());//插入原数据表

                BulkInsertObject.BulkInsert(_dbConn, "Pd_Debit", vourcherDebits);//插入中间表(借方表)

                BulkInsertObject.BulkInsert(_dbConn, "Pd_Vourcher_Warning", varcherWarnings);//插入预警表
            }
            return GetEntitys<PdEntityDebit>($"select * from Pd_Debit where GroupId = '{groupCode}' ");
        }

        /// <summary>
        /// 项目预警
        /// </summary>
        /// <param name="projectDicc"></param>
        /// <param name="projects"></param>
        /// <param name="vourcher"></param>
        /// <param name="debits"></param>
        /// <param name="vourcherDebits"></param>
        /// <param name="customers"></param>
        /// <param name="isMonthlyCalc"></param>
        /// <returns></returns>
        private List<PdEntityVourcherWarning> ProjectProcessing(Dictionary<string, string> projectDicc, List<PdEntityVourcherProject> projects, PdEntityVourcher vourcher, ref List<PdEntityDebit> debits, ref List<PdEntityDebit> vourcherDebits, List<PdEntityVourcherCustomer> customers, bool isMonthlyCalc = false)
        {
            var warnings = new List<PdEntityVourcherWarning>();

            //if (vourcher.集团代码 == "0001") //外部才插入
            //{
            //陆家嘴集团的项目预警
            var pList = new List<string[]>();
            var cList = new List<string[]>();
            var isCount = true;
 
            foreach (var fzz in vourcher.凭证辅助账)
            {
                GetVourcherFzz(fzz, ref pList, ref cList);
                foreach (var project in pList)
                {
                    isCount = true;
                    foreach (var customer in cList)
                    {
                        if (!InternalCustomer(customers, customer[0], customer[1])) //判断是不是外部客商
                        {
                            if (!IsRepeat(debits, vourcher, project[0], project[1]))
                            {
                                var projectKey = new KeyValuePair<string, string>(project[0], project[1]);
                                var warning = ProjectProcessingWarning(projectKey, vourcher, ref debits, ref vourcherDebits, projects, isMonthlyCalc);
                                if (warning != null)
                                    warnings.Add(warning);
                            }

                        }
                        // 内部客商不进行计算，  有项目 没客商 都算 外部项目计算，有项目有客商 进行内外区分
                        isCount = false;
                        break;
                    }
                    if (isCount)
                    {
                        if (!IsRepeat(debits, vourcher, project[0], project[1]))
                        {
                            var projectKey = new KeyValuePair<string, string>(project[0], project[1]);
                            var warning = ProjectProcessingWarning(projectKey, vourcher, ref debits, ref vourcherDebits,
                                projects, isMonthlyCalc);
                            if (warning != null)
                                warnings.Add(warning);
                        }
                    }
                }
                pList.Clear(); cList.Clear();
            }
            //}
            //else
            //{
            //    foreach (var project in projectDicc)
            //    {
            //        var warning = ProjectProcessingWarning(project, vourcher, ref debits, ref vourcherDebits, projects,
            //            isMonthlyCalc);
            //        if (warning != null)
            //            warnings.Add(warning);
            //    }
            //}

            return warnings;
        }

        private PdEntityVourcherWarning ProjectProcessingWarning(KeyValuePair<string, string> item, PdEntityVourcher vourcher, ref List<PdEntityDebit> debits, ref List<PdEntityDebit> vourcherDebits, List<PdEntityVourcherProject> projects, bool isMonthlyCalc)
        {
            var debit = NewDebit(vourcher, 1, item.Key, string.Empty, item.Value);
            var project = GetProject(projects, item.Key, item.Value);
    
            if (project != null)
            {
                debit.ProjectCode = project.BigProjectCode;
                debit.BigProjectName = project.BigProjectName;
                debits.Add(debit);//累计前先插入此次记录在进行累计
                vourcherDebits.Add(debit);
                if (project.CountFlag == 1) //按年度统计
                {
                    decimal amount;
                    if (isMonthlyCalc)
                        //amount = debits.Where(t => t.SubsidiaryType == 1 && t.SubsidiaryCode == item.Key &&
                        //                t.ProjectName == item.Value && t.PostingDate.Year == vourcher.记账日期.Year &&
                        //                t.PostingDate <= GetLastDayOfLastMonth()).Sum(t => t.Amount);
                        amount = debits.Where(t => t.SubsidiaryType == 1 && t.SubsidiaryCode == project.BigProjectCode &&
                                                   t.BigProjectName == project.BigProjectName && t.PostingDate.Year == vourcher.记账日期.Year &&
                                                   t.PostingDate <= GetLastDayOfLastMonth()).Sum(t => t.Amount);
                    else
                        amount = debits.Where(t => t.SubsidiaryType == 1 && t.SubsidiaryCode == project.BigProjectCode &&
                                        t.ProjectName == project.BigProjectName && t.PostingDate.Year == vourcher.记账日期.Year)
                            .Sum(t => t.Amount);

                    if (amount > project.Threshold&&amount>decimal.Parse("50000000.00")) //当前的项目累计金额>该项目阀值
                        return NewVourcherWarning(vourcher, WarningType.Project, item.Key, item.Value, vourcher.原币金额, $"[{project.BigProjectName}]累计金额超过项目预算金额[{project.Threshold}]", project.BigProjectCode, project.BigProjectName);
                }
                else //否则所有时间断累计
                {
                    var amount = debits.Where(t => t.SubsidiaryType == 1 && t.SubsidiaryCode == project.BigProjectCode
                                                   && t.ProjectName == project.BigProjectName).Sum(t => t.Amount);
                    if (amount > project.Threshold && amount > decimal.Parse("50000000.00")) //当前的项目累计金额>该项目阀值
                        return NewVourcherWarning(vourcher, WarningType.Project, item.Key, item.Value, vourcher.原币金额,
                            $"[{project.BigProjectName}]累计金额超过项目预算金额[{project.Threshold}]", project.BigProjectCode, project.BigProjectName);
                }
            }
            else //项目未找到 新项目预警
            {
                debits.Add(debit);//累计前先插入此次记录在进行累计
                vourcherDebits.Add(debit);
                return NewVourcherWarning(vourcher, WarningType.Project, item.Key, item.Value, vourcher.原币金额,
                    $"新项目[{item.Value}]");
            }
            return null;
        }


        /// <summary>
        /// 项目公司预警
        /// </summary>
        /// <param name="v"></param>
        /// <param name="projectCompany"></param>
        /// <param name="vourcherDebits"></param>
        /// <param name="debits"></param>
        /// <returns></returns>
        private List<PdEntityVourcherWarning> ProjectCompanyProcessing(PdEntityVourcher v, PdEntityOrganization projectCompany, ref List<PdEntityDebit> debits, ref List<PdEntityDebit> vourcherDebits)
        {
            var warnings = new List<PdEntityVourcherWarning>();
            //debits 累计之前先插入当前记录
            debits.Add(NewDebit(v, 1, projectCompany.CompanyCode, string.Empty, projectCompany.CompanyName, true));
            vourcherDebits.Add(NewDebit(v, 1, projectCompany.CompanyCode, string.Empty, projectCompany.CompanyName, true));
            var projectCompanyMoneys = debits.Where(t => t.SubsidiaryType == 1 && t.PostingDate.Year == v.记账日期.Year && t.CompanyCode == v.公司编码 && t.GroupId == v.集团代码).Sum(t => t.Amount);

            if (projectCompanyMoneys > projectCompany.Threshold && projectCompanyMoneys > decimal.Parse("50000000.00"))
                //插入预警表，表示项目累计预警
                warnings.Add(NewVourcherWarning(v, WarningType.Project, string.Empty, string.Empty, v.原币金额, $"[项目公司]累计金额超过项目预算金额[{projectCompany.Threshold}]"));

            return warnings;
        }

        /// <summary>
        /// 凭证预警
        /// </summary>
        /// <param name="organizations"></param>
        /// <param name="v"></param>
        /// <returns></returns>
        private PdEntityVourcherWarning VourcherProcessing(List<PdEntityOrganization> organizations, PdEntityVourcher v)
        {
            var organization = organizations.FirstOrDefault(t => $"{t.GroupId}-{t.CompanyCode}" == $"{v.集团代码}-{v.公司编码}");
            if (organization == null)
                return null;

            if (v.流入资金)
            {
                if (v.原币金额 > organization.InflowThreshold) //借贷方向为1的时候流入阀值对比
                    return NewVourcherWarning(v, WarningType.Vourcher, string.Empty, string.Empty, v.原币金额,
                        "单笔金额超过预警阀值!");
            }
            else //借贷方向为0的时候
            {
                if (v.原币金额 > organization.Threshold)
                    return NewVourcherWarning(v, WarningType.Vourcher, string.Empty, string.Empty, v.原币金额,
                        "单笔金额超过预警阀值!");
            }
            return null;
        }

        /// <summary>
        /// 增加余额
        /// </summary>
        /// <param name="groupCode"></param>
        /// <param name="groupName"></param>
        /// <param name="balances"></param>
        /// <returns></returns>
        private string AddBalances(string groupCode, string groupName, string balances)
        {
            try
            {
                if (string.IsNullOrEmpty(balances) || balances == "[]")
                    return string.Empty;

                var balance = tl.Decrypt(balances);//解密 4.6写法
                balance = zt.GZipDecompressString(Encoding.GetEncoding("utf-8"), balance);//先base64还原、再来解压
                var rootBalances = balance.ToObject<List<RootBalance>>();
                var balanceEntitys = new List<PdEntityBalance>();
                foreach (var item in rootBalances)
                {
                    balanceEntitys.Add(new PdEntityBalance
                    {
                        GroupId = groupCode,
                        GroupName = groupName,
                        CompanyCode = item.公司编码,
                        CompanyName = item.公司名称,
                        Currency = item.币别,
                        // ExchangeRate=item.
                        SubjectCode = item.科目代码,
                        SubjectName = item.科目名称,
                        StartPostingPriod = item.开始会计期间,
                        EndPostingPriod = item.结束会计期间,
                        InitialBalance = item.期初余额,
                        EndingBalance = item.期末余额,
                        CurrentCreditBalance = item.本期贷方发生额,
                        CurrentDebitBalance = item.本期借方发生额,
                        CurrentCreditYearBalance = item.本年贷方发生额,
                        CurrentDebitYearBalance = item.本年借方发生额
                    });
                }

                //日志记录
                _logger.LogInformation($"{groupName}--余额数据条目:{balanceEntitys.Count}");

                BulkInsertObject.BulkInsert(_dbConn, "Pd_Balance", balanceEntitys);//插入余额表

                return $"{groupName}--提取余额数据量:{balanceEntitys.Count}";

            }
            catch (Exception ex)
            {
                _logger.LogError($"{groupName}--插入余额数据异常:{ex.Message}");
                return $"{groupName}--插入余额数据异常:{ex.Message}";
            }
        }

        /// <summary>
        /// 获取debit对象
        /// </summary>
        /// <param name="vourcher"></param>
        /// <param name="sType"></param>
        /// <param name="sCode"></param>
        /// <param name="customerName"></param>
        /// <param name="projectName"></param>
        /// <param name="isProjectCompany"></param>
        /// <param name="bigProjectCode"></param>
        /// <param name="bigProjectName"></param>
        /// <returns></returns>
        private PdEntityDebit NewDebit(PdEntityVourcher vourcher, int sType, string sCode, string customerName, string projectName, bool isProjectCompany = false, string bigProjectCode = "", string bigProjectName = "")
        {
            var fzz = vourcher.凭证辅助账.FirstOrDefault(t => t.核算项.FirstOrDefault(r => r.编码 == sCode) != null);
            var amount = GetAmount(isProjectCompany, fzz, vourcher.原币金额);

            return new PdEntityDebit
            {
                GroupId = vourcher.集团代码,
                GroupName = vourcher.集团名称,
                CompanyCode = vourcher.公司编码,
                CompanyName = vourcher.公司名称,
                CompanyUniqueId = $"{vourcher.集团代码}-{vourcher.公司编码}",
                VourcherSqNo = vourcher.凭证ID,
                PostingDate = vourcher.记账日期,
                BusinessDate = vourcher.业务日期,
                EntryDate = vourcher.录入日期,
                EntryNo = vourcher.分录序号,
                PostingPriod = vourcher.会计期间,
                VourcherType = vourcher.凭证类型,
                VourcherNo = vourcher.凭证号,
                VourcherSummary = vourcher.摘要,
                VourcherSubject = vourcher.科目代码,
                SubjectName = vourcher.科目名称,
                Currency = vourcher.币别,
                ExchangeRate = vourcher.汇率,
                Amount = amount,
                AmountDebit = amount,
                AmountCredit = vourcher.贷方金额,
                AmountFlow = vourcher.流入资金,//流入流出资金标识
                SujectType = vourcher.科目分类,//科目分类标记
                SubsidiaryType = sType,
                SubsidiaryCode = sCode,
                CustomerName = customerName,
                ProjectName = projectName,
                BigProjectName = bigProjectName,
                ProjectCode = bigProjectCode
            };
        }

        /// <summary>
        /// 创建新的凭证预警对象
        /// </summary>
        /// <param name="vourcher"></param>
        /// <param name="type"></param>
        /// <param name="codeId"></param>
        /// <param name="codeName"></param>
        /// <param name="amount"></param>
        /// <param name="vourcherContent"></param>
        /// <param name="bigProjectCode"></param>
        /// <param name="bigProjectName"></param>
        /// <returns></returns>
        private PdEntityVourcherWarning NewVourcherWarning(PdEntityVourcher vourcher, WarningType type, string codeId, string codeName, decimal amount, string vourcherContent, string bigProjectCode = "", string bigProjectName = "")
        {
            return new PdEntityVourcherWarning
            {
                GroupId = vourcher.集团代码,
                GroupName = vourcher.集团名称,
                CompanyCode = vourcher.公司编码,
                CompanyName = vourcher.公司名称,
                CompanyUniqueId = $"{vourcher.集团代码}-{vourcher.公司编码}",
                VourcherSqNo = vourcher.凭证ID,
                PostingDate = vourcher.记账日期,
                BusinessDate = vourcher.业务日期,
                EntryDate = vourcher.录入日期,
                EntryNo = vourcher.分录序号,
                PostingPriod = vourcher.会计期间,
                VourcherType = vourcher.凭证类型,
                VourcherNo = vourcher.凭证号,
                VourcherSummary = vourcher.摘要,
                VourcherSubject = vourcher.科目代码,
                SubjectName = vourcher.科目名称,
                Currency = vourcher.币别,
                ExchangeRate = vourcher.汇率,
                Amount = vourcher.原币金额,
                AmountDebit = vourcher.借方金额,
                AmountCredit = vourcher.贷方金额,
                AmountFlow = vourcher.流入资金,//流入流出资金标识
                SujectType = vourcher.科目分类,//科目分类标记
                WarningType = type,
                // WaringStatus = 0,//WarningStatus.Uncommitted,
                ProjectID = type == WarningType.Project ? codeId : string.Empty,
                ProjectName = type == WarningType.Project ? codeName : string.Empty,

                CustomerID = type == WarningType.Customer ? codeId : string.Empty,
                CustomerName = type == WarningType.Customer ? codeName : string.Empty,

                WarningAmount = amount,
                VourcherContent = vourcherContent,
                RowModifyDateTime = DateTime.Now,

                BigProjectName = bigProjectName,
                BigProjectCode = bigProjectCode
            };
        }

        /// <summary>
        /// 获取分类标签
        /// </summary>
        /// <param name="v"></param>
        /// <param name="subjects"></param>
        /// <param name="customers"></param>
        /// <returns></returns>
        private string GetSubjectTag(PdEntityVourcher v, List<PdEntitySubject> subjects, List<PdEntityVourcherCustomer> customers)
        {
            if (subjects.Count == 0)
                return string.Empty;

            var sub = subjects.FirstOrDefault(t => t.SubjectCode == v.科目代码);
            if (sub != null)
                return CheckSubjectA1(sub.SubjectSign, v, customers);

            var suject = v.科目代码;
            while (suject.Contains("."))
            {
                var lastIndex = suject.LastIndexOf(".", suject.Length);
                suject = suject.Substring(0, lastIndex);
                sub = subjects.FirstOrDefault(t => t.SubjectCode == suject);
                if (sub != null)
                    return CheckSubjectA1(sub.SubjectSign, v, customers);
            }
            return CheckSubjectA1(string.Empty, v, customers);
        }

        /// <summary>
        /// 检查科目代码是a1类
        /// </summary>
        /// <param name="subjectSign"></param>
        /// <param name="v"></param>
        /// <param name="customers"></param>
        /// <returns></returns>
        private string CheckSubjectA1(string subjectSign, PdEntityVourcher v, List<PdEntityVourcherCustomer> customers)
        {
            if (v.集团代码 == "0001")
            {
                var dicc = GetSubsidiary(v);
                if (subjectSign == "a1")
                {
                    if (dicc.Item2.Count == 0)
                        return subjectSign;

                    foreach (var customer in dicc.Item2)
                    {//外部客商才返回a1
                        if (!InternalCustomer(customers, customer.Key, customer.Value))
                            return "a1";
                    }
                    //内部客商则需要找 应收，应付 、其他 再做一次匹配 得到是否是 5类 或者3类
                    if (v.科目代码.Contains("1122") || v.科目代码.Contains("1221") || v.科目代码.Contains("2202") ||
                        v.科目代码.Contains("2241"))
                        return "5";

                    return "3";
                }
                if (subjectSign == "a2")
                {
                    if (dicc.Item2.Count == 0)
                        return subjectSign;

                    foreach (var customer in dicc.Item2)
                    {//外部客商才返回a2
                        if (!InternalCustomer(customers, customer.Key, customer.Value))
                            return "a2";
                    }
                    return "4";
                }

                //判断是否是内部的资金往来
                if (v.科目代码.Contains("1122") || v.科目代码.Contains("1221") || v.科目代码.Contains("2202") ||
                    v.科目代码.Contains("2241"))
                {
                    foreach (var customer in dicc.Item2)
                    {
                        if (InternalCustomer(customers, customer.Key, customer.Value))
                            return "5";
                    }
                }

                //判断是否内部交易
                if (v.科目代码.Contains("5001") || v.科目代码.Contains("5002") || v.科目代码.Contains("5003") ||
                    v.科目代码.Contains("6602") || v.科目代码.Contains("6603") || v.科目代码.Contains("6401"))
                {
                    foreach (var customer in dicc.Item2)
                    {
                        if (InternalCustomer(customers, customer.Key, customer.Value))
                            return "3";
                    }
                }
            }//陆家嘴

            if (v.集团代码 == "0011")
            {
                var dicc = GetSubsidiary(v);
                if (subjectSign == "a1")
                {
                    if (dicc.Item2.Count == 0)
                        return subjectSign;

                    foreach (var customer in dicc.Item2)
                    {//外部客商才返回a1
                        if (!InternalCustomer(customers, customer.Key, customer.Value))
                            return "a1";
                    }
                    //内部客商则需要找 应收，应付 、其他 再做一次匹配 得到是否是 5类 或者3类
                    if (v.科目代码.Contains("1123") || v.科目代码.Contains("2202") || v.科目代码.Contains("2203") ||
                        v.科目代码.Contains("6401") || v.科目代码.Contains("6402"))
                        return "3";

                    return "a1";
                }

                if (subjectSign == "a2")
                {
                    if (dicc.Item2.Count == 0)
                        return subjectSign;

                    foreach (var customer in dicc.Item2)
                    {//外部客商才返回a2
                        if (!InternalCustomer(customers, customer.Key, customer.Value))
                            return "a2";
                    }
                    return "4";
                }

                if (v.科目代码.Contains("1221") || v.科目代码.Contains("1495") || v.科目代码.Contains("2245"))
                {
                    foreach (var customer in dicc.Item2)
                    {
                        if (InternalCustomer(customers, customer.Key, customer.Value))
                            return "5";
                    }
                }
            }//外高桥

            if (v.集团代码 == "0012")//张江高科
            {
                var dicc = GetSubsidiary(v);
                if (subjectSign == "a1")
                {
                    if (dicc.Item2.Count == 0)
                        return subjectSign;

                    foreach (var customer in dicc.Item2)
                    {//外部客商才返回a1
                        if (!InternalCustomer(customers, customer.Key, customer.Value))
                            return "a1";
                    }
                    //内部客商则需要找 应收，应付 、其他 再做一次匹配 得到是否是 5类 或者3类
                    if (v.科目代码.Contains("2202") || v.科目代码.Contains("2241.05"))
                        return "5";

                    return "3";
                }

                if (subjectSign == "a2")
                {
                    if (dicc.Item2.Count == 0)
                        return subjectSign;

                    foreach (var customer in dicc.Item2)
                    {//外部客商才返回a2
                        if (!InternalCustomer(customers, customer.Key, customer.Value))
                            return "a2";
                    }
                    return "4";
                }

                if (v.科目代码.Contains("1231.10") || v.科目代码.Contains("2241.13"))
                {
                    foreach (var customer in dicc.Item2)
                    {
                        if (InternalCustomer(customers, customer.Key, customer.Value))
                            return "5";
                    }
                }
            }

            return subjectSign;
        }


        #region Helper Method

        private bool IsRepeat(List<PdEntityDebit> debits, PdEntityVourcher v, string key, string value)
        {
            return debits.Any(t =>
                t.EntryNo == v.分录序号 && t.SubsidiaryCode == key && t.ProjectName == value &&
                t.VourcherSqNo == v.凭证ID);
        }


        /// <summary>
        /// GetProject
        /// </summary>
        /// <param name="projects"></param>
        /// <param name="projectCode"></param>
        /// <param name="projectName"></param>
        /// <returns></returns>
        private PdEntityVourcherProject GetProject(List<PdEntityVourcherProject> projects, string projectCode, string projectName)
        {
            //t.ProjectName == projectName.Trim() ,为什么加Trim, 有特别的名称最后含有空格，而含有空格却查询不出来,所以加Trim
            return projects.FirstOrDefault(t => t.ProjectCode == projectCode && (t.ProjectName == projectName.Trim() || t.ProjectName == projectName));
        }

        /// <summary>
        /// 外部客商预警
        /// </summary>
        /// <param name="customer"></param>
        /// <param name="originalAmount"></param>
        /// <param name="vourcher"></param>
        /// <param name="item"></param>
        /// <param name="debits"></param>
        /// <param name="isMonthlyCalc"></param>
        /// <returns></returns>
        private PdEntityVourcherWarning ExternalCustomerWarning(PdEntityVourcherCustomer customer, decimal originalAmount, PdEntityVourcher vourcher, KeyValuePair<string, string> item, List<PdEntityDebit> debits, bool isMonthlyCalc)
        {
            if (customer.InternalCustomer == "否") //如果是内部客商则不预警
            {
                if (originalAmount > customer.Threshold) //单笔阀值预警计算（当前辅助账的金额对比）
                    return NewVourcherWarning(vourcher, WarningType.Customer, item.Key, item.Value, originalAmount,
                        "单笔金额超过预警阀值");

                decimal amount;
                if (isMonthlyCalc)
                    amount = debits.Where(t =>
                            t.SubsidiaryType == 2 && t.SubsidiaryCode == item.Key &&
                            t.CompanyCode == vourcher.公司编码 && t.PostingDate <= vourcher.记账日期 &&
                            t.PostingDate >= vourcher.记账日期.AddDays(-30) && t.PostingDate <= GetLastDayOfLastMonth())
                        .Sum(t => t.Amount);
                else
                    amount = debits
                        .Where(t => t.SubsidiaryType == 2 && t.SubsidiaryCode == item.Key &&
                                    t.CompanyCode == vourcher.公司编码 && t.PostingDate <= vourcher.记账日期 &&
                                    t.PostingDate >= vourcher.记账日期.AddDays(-30)).Sum(t => t.Amount);

             //   if (amount > customer.Threshold * 3) //累计预警计算（当前的累计阀值是否大于 当前客商辅助账金额的3倍）
              //      return NewVourcherWarning(vourcher, WarningType.Customer, item.Key, item.Value,
              //          amount, $"[{item.Value}]累计30日滚动金额超过单次预警值3倍预警!");
            }
            return null;
        }


        /// <summary>
        /// 获取中间表金额
        /// </summary>
        /// <param name="isProjectCompany"></param>
        /// <param name="fzz"></param>
        /// <param name="vourcherAmount"></param>
        /// <returns></returns>
        private decimal GetAmount(bool isProjectCompany, 凭证辅助账 fzz, decimal vourcherAmount)
        {
            if (isProjectCompany)
                return vourcherAmount;

            return fzz == null ? 0 : fzz.原币金额;
        }

        /// <summary>
        /// 是否是内部客商
        /// </summary>
        /// <param name="customers"></param>
        /// <param name="customerCode"></param>
        /// <param name="customerName"></param>
        /// <returns></returns>
        private bool InternalCustomer(List<PdEntityVourcherCustomer> customers, string customerCode, string customerName)
        {
            //return customers.Any(t => t.CustomerCode == customerCode && t.CustomerName == customerName && t.InternalCustomer == "是");
            return customers.Any(t => t.CustomerName == customerName && t.InternalCustomer == "是");
        }

        private void GetVourcherFzz(凭证辅助账 fzz, ref List<string[]> pList, ref List<string[]> cList)
        {
            foreach (var hsx in fzz.核算项)
            {
                if (hsx.核算项目.Contains("项目"))
                {
                    pList.Add(new[] { hsx.编码, hsx.名称 });
                }
                if (hsx.核算项目.Contains("客") || hsx.核算项目.Contains("商"))
                {
                    cList.Add(new[] { hsx.编码, hsx.名称 });
                }
            }
        }

        /// <summary>
        /// 获取辅助账字典元组
        /// </summary>
        /// <param name="vourcher"></param>
        /// <returns></returns>
        private Tuple<Dictionary<string, string>, Dictionary<string, string>> GetSubsidiary(PdEntityVourcher vourcher)
        {
            var projectDicc = new Dictionary<string, string>();
            var customerDicc = new Dictionary<string, string>();

            foreach (var item in vourcher.凭证辅助账)
            {
                foreach (var hsx in item.核算项)
                {
                    if (hsx.核算项目.Contains("项目"))
                    {
                        if (!projectDicc.Keys.Contains(hsx.编码))
                            projectDicc.Add(hsx.编码, hsx.名称);
                    }
                    else if (hsx.核算项目.Contains("客") || hsx.核算项目.Contains("商"))
                    {
                        if (!customerDicc.Keys.Contains(hsx.编码))
                            customerDicc.Add(hsx.编码, hsx.名称);
                    }
                }
            }
            return Tuple.Create(projectDicc, customerDicc);
        }

        /// <summary>
        /// 获取上个月第一天
        /// </summary>
        /// <returns></returns>
        public DateTime GetFirstDayOfLastMonth()
        {
            return DateTime.Now.AddDays(1 - DateTime.Now.Day).AddMonths(-1);
        }

        /// <summary>
        /// 获取上个月最后一天
        /// </summary>
        /// <returns></returns>
        public DateTime GetLastDayOfLastMonth()
        {
            return DateTime.Now.AddDays(1 - DateTime.Now.Day).AddDays(-1);
        }

        #endregion



        /**
        public async Task<string> Test()
        {
            //_logger.LogError("test error");
            _logger.LogInformation("Delete data");


            var vourchers = _context.PdVourchers.Include(t => t.凭证辅助账).ThenInclude(r => r.核算项)
                .Where(t => t.RowModifyDateTime > Convert.ToDateTime("2017-11-2")).ToList();

            var warning = _context.PdEntityVourcherWarnings.Where(t => t.RowModifyDateTime > Convert.ToDateTime("2017-11-2"));


            var debits = _context.PdDebits.Where(t => t.RowModifyDateTime > Convert.ToDateTime("2017-11-2"));

            //  var balances = _context.Pd_Balances.Where(t => t.RowModifyDateTime > Convert.ToDateTime("2017-11-2"));

            _context.PdVourchers.RemoveRange(vourchers);

            _context.PdEntityVourcherWarnings.RemoveRange(warning);

            _context.PdDebits.RemoveRange(debits);

            //   _context.Pd_Balances.RemoveRange(balances);
            _context.SaveChanges();

            _logger.LogInformation("Delete data is Ok");



            //var obj = _context.Pd_Balances.Where(t => t.RowModifyDateTime > Convert.ToDateTime("2017-10-17")).ToList();

            //var balanceList = new List<PdEntityBalance>();
            //foreach (var item in obj)
            //{
            //    balanceList.Add(new PdEntityBalance
            //    {
            //        GroupId = item.GroupId,
            //        GroupName = item.GroupName,
            //        CompanyCode = item.CompanyCode,
            //        CompanyName = item.CompanyName,
            //        Currency = item.Currency,
            //        // ExchangeRate=item.
            //        SubjectCode = item.SubjectCode,
            //        SubjectName = item.SubjectName,
            //        StartPostingPriod = item.StartPostingPriod,
            //        EndPostingPriod = item.EndPostingPriod,
            //        InitialBalance = item.InitialBalance,
            //        EndingBalance = item.EndingBalance,
            //        CurrentCreditBalance = item.CurrentCreditBalance,
            //        CurrentDebitBalance = item.CurrentDebitBalance,
            //        CurrentCreditYearBalance = item.CurrentCreditYearBalance,
            //        CurrentDebitYearBalance = item.CurrentDebitYearBalance
            //    });
            //}
            //await _context.Pd_Balances.AddRangeAsync(balanceList);
            //await _context.SaveChangesAsync();
            return "OK";
        } 
            private string CheckData()
            {
               
                var single = _context.PdEntityVourcherWarnings.Where(t =>
                    t.PostingDate > Convert.ToDateTime("2017-1-1") && t.WarningType == WarningType.Customer &&
                    t.VourcherContent.Contains("单笔")).Count();
    
                var newCustomer = _context.PdEntityVourcherWarnings.Where(t =>
                    t.PostingDate > Convert.ToDateTime("2017-1-1") && t.WarningType == WarningType.Customer &&
                    t.VourcherContent.Contains("新客商")).Count();
    
                var countTotal = _context.PdEntityVourcherWarnings.Where(t =>
                    t.PostingDate > Convert.ToDateTime("2017-1-1") && t.WarningType == WarningType.Customer &&
                    t.VourcherContent.Contains("累计")).Count();
    
                var enterpriseQuantity = _context.PdEntityVourcherWarnings.Where(t =>
                    t.PostingDate > Convert.ToDateTime("2017-1-1") && t.WarningType == WarningType.Customer &&
                    t.VourcherContent.Contains("累计")).GroupBy(t => t.CompanyName).Distinct();
               
         return String.Empty;
     }
      **/
    }
}
